This brief tutorial will introduce you to the basic usage of the AlphaTims API in Python. It is divided in five parts:
If AlphaTims is not installed yet, install it with (NOTE it is highly recommended to do this in a clean conda environment):
#!pip install "alphatims[plotting]"
Import the AlphaTims utils libraries to use it (NOTE: this may take a few seconds):
import alphatims.utils
By default all but one CPU threads are used by AlphaTims. A log file is by default written to the log folder in AlphaTims root directory.
Both uptions can be updated with the commands:
alphatims.utils.set_threads(4)
log_file_name = alphatims.utils.set_logger(
log_file_name="tutorial_log.txt",
overwrite=True
)
To ensure full reproducibility, it is best to always log the details of your AlphaTims installation and OS:
alphatims.utils.show_platform_info()
alphatims.utils.show_python_info()
2021-04-22 16:59:10> Platform information: 2021-04-22 16:59:10> system - Darwin 2021-04-22 16:59:10> release - 19.6.0 2021-04-22 16:59:10> version - 10.15.7 2021-04-22 16:59:10> machine - x86_64 2021-04-22 16:59:10> processor - i386 2021-04-22 16:59:10> cpu count - 8 2021-04-22 16:59:10> cpu frequency - 2300.00 Mhz 2021-04-22 16:59:10> ram - 23.7/32.0 Gb (available/total) 2021-04-22 16:59:10> 2021-04-22 16:59:10> Python information: 2021-04-22 16:59:10> alphatims - 0.2.5 2021-04-22 16:59:10> bokeh - 2.2.3 2021-04-22 16:59:10> click - 7.1.2 2021-04-22 16:59:10> datashader - 0.12.1 2021-04-22 16:59:10> h5py - 3.2.1 2021-04-22 16:59:10> hvplot - 0.7.1 2021-04-22 16:59:10> numba - 0.53.1 2021-04-22 16:59:10> pandas - 1.2.3 2021-04-22 16:59:10> psutil - 5.8.0 2021-04-22 16:59:10> python - 3.8.8 2021-04-22 16:59:10> pyzstd - 0.14.4 2021-04-22 16:59:10> selenium - 3.141.0 2021-04-22 16:59:10> tqdm - 4.60.0 2021-04-22 16:59:10>
Now you can load the other AlphaTims libraries. When an editable version is installed with the command (pip install -e alphatims), libraries can interactively be reloaded with the following command when the source code is modified:
import alphatims.bruker
import alphatims.plotting
import importlib
def reload():
importlib.reload(alphatims.utils)
importlib.reload(alphatims.bruker)
importlib.reload(alphatims.plotting)
alphatims.utils.set_threads(4)
alphatims.utils.set_logger(log_file_name="tutorial_log.txt")
# NOTE, calling reload() updates global variables in alphatims.utils,
# so e.g. any alphatims.utils.set_* function need to be redone
# after reloading, unless you specify this in the reload function.
2021-04-22 16:59:11> WARNING: No Bruker libraries are available for this operating system. Intensities are uncalibrated, resulting in (very) small differences. However, mobility and m/z values need to be estimated. While this estimation often returns acceptable results with errors < 0.02 Th, huge errors (e.g. offsets of 6 Th) have already been observed for some samples! 2021-04-22 16:59:11>
Note that AlphaTims is fully documented and that help functions are available, e.g.:
help(alphatims.utils.set_threads)
Help on function set_threads in module alphatims.utils:
set_threads(threads: int, set_global: bool = True) -> int
Parse and set the (global) number of threads.
Parameters
----------
threads : int
The number of threads.
If larger than available cores, it is trimmed to the available maximum.
If 0, it is set to the maximum cores available.
If negative, it indicates how many cores NOT to use.
set_global : bool
If False, the number of threads is only parsed to a valid value.
If True, the number of threads is saved as a global variable.
Default is True.
Returns
-------
: int
The number of threads.
A complete Bruker .d folder (available for download on AlphaTims' GitHub page) can be read into memory with the following command:
IMPORTANT NOTE: available RAM should be roughly twice the size of the Bruker .d folder. This is easily checked with the output of alphatims.utils.show_platform_info()
# reload()
bruker_d_folder_name = "/Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_DDA_21min_8cm_S1-C10_1_22476.d"
data = alphatims.bruker.TimsTOF(bruker_d_folder_name)
2021-04-22 16:59:14> Importing data from /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_DDA_21min_8cm_S1-C10_1_22476.d 2021-04-22 16:59:14> Reading frame metadata for /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_DDA_21min_8cm_S1-C10_1_22476.d 2021-04-22 16:59:15> Reading 11,886 frames with 295,251,252 detector strikes for /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_DDA_21min_8cm_S1-C10_1_22476.d
100%|██████████| 11886/11886 [00:02<00:00, 4634.51it/s]
2021-04-22 16:59:18> Indexing /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_DDA_21min_8cm_S1-C10_1_22476.d... 2021-04-22 16:59:18> Succesfully imported data from /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_DDA_21min_8cm_S1-C10_1_22476.d
In our tutorial, we used MacOS. During our very first command import alphatims.bruker, we noticed a warning message stating that "No Bruker libraries are available [...], mobility and m/z values need to be estimated". For this tutorial dataset these estimations are fine, but in general we advise to use Windows or Linux to avoid estimation. After importing the data on a Windows or Linux PC, it can be saved to a portable HDF file:
hdf_file_name = data.save_as_hdf(
directory=data.directory,
file_name=f"{data.sample_name}.hdf",
overwrite=True
)
2021-04-22 16:59:18> Writing TimsTOF data to /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_DDA_21min_8cm_S1-C10_1_22476.hdf.
100%|██████████| 31/31 [00:00<00:00, 39.89it/s]
2021-04-22 16:59:19> Succesfully wrote TimsTOF data to /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_DDA_21min_8cm_S1-C10_1_22476.hdf.
This HDF is a single portable file containing all raw data, that can be accessed on all Operating Systems regardless of how it was created. As such, reading of correct mz and mobility values can be done on a Windows or Linux machine, while further processing can be done on any other OS. An additional benefit is that loading of HDF files is roughly three times faster than loading of a raw Bruker .d folder.
A TimsTOF data object can be sliced in the five following dimensions:
In each dimension, you can slice indices with integers and values with floats just as you would do with any normal Python object. Additionally it allows slicing with iterable just as in Numpy. The result of a slicing operation is a pd.DataFrame by default. If the slicing seems confusing, remember that you can always look at the help function.
# help(data)
As a simple example, datapoints for the precursor with index 999 can be obtained by slicing the data in the third (i.e. QUAD) dimension (The first time you slice the data, it can be relatively slow because AlphaTims uses just-in-time (JIT) compilation from the Numba package. All subsequent slices should be a lot faster):
df = data[:, :, 999]
df
| raw_indices | frame_indices | scan_indices | precursor_indices | tof_indices | rt_values | mobility_values | quad_low_mz_values | quad_high_mz_values | mz_values | intensity_values | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 4642464 | 1710 | 812 | 999 | 179560 | 182.041606 | 0.725000 | 377.714229 | 379.714229 | 586.314189 | 84 |
| 1 | 4642465 | 1710 | 813 | 999 | 148482 | 182.041606 | 0.723922 | 377.714229 | 379.714229 | 473.227756 | 152 |
| 2 | 4642466 | 1710 | 813 | 999 | 151763 | 182.041606 | 0.723922 | 377.714229 | 379.714229 | 484.595143 | 63 |
| 3 | 4642467 | 1710 | 813 | 999 | 179830 | 182.041606 | 0.723922 | 377.714229 | 379.714229 | 587.349701 | 35 |
| 4 | 4642468 | 1710 | 815 | 999 | 152231 | 182.041606 | 0.721767 | 377.714229 | 379.714229 | 486.227575 | 125 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 211 | 4643095 | 1711 | 831 | 999 | 198049 | 182.147891 | 0.704526 | 377.714229 | 379.714229 | 659.334531 | 138 |
| 212 | 4643096 | 1711 | 832 | 999 | 79376 | 182.147891 | 0.703448 | 377.714229 | 379.714229 | 265.148616 | 112 |
| 213 | 4643097 | 1711 | 832 | 999 | 197806 | 182.147891 | 0.703448 | 377.714229 | 379.714229 | 658.347045 | 73 |
| 214 | 4643098 | 1711 | 832 | 999 | 198051 | 182.147891 | 0.703448 | 377.714229 | 379.714229 | 659.342661 | 114 |
| 215 | 4643099 | 1711 | 832 | 999 | 214846 | 182.147891 | 0.703448 | 377.714229 | 379.714229 | 729.386508 | 119 |
216 rows × 11 columns
Other slicing options include traditional Python slices or iterables. Multiple dimensions can be defined at the same time, for instance:
df = data[:400.5, 500:700, 0, 400.0: 400.5, [50, 87, 116]]
df
| raw_indices | frame_indices | scan_indices | precursor_indices | tof_indices | rt_values | mobility_values | quad_low_mz_values | quad_high_mz_values | mz_values | intensity_values | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 221445 | 146 | 575 | 0 | 126345 | 15.952364 | 0.980388 | -1.0 | -1.0 | 400.057569 | 87 |
| 1 | 1104358 | 585 | 682 | 0 | 126352 | 62.533610 | 0.865086 | -1.0 | -1.0 | 400.079736 | 50 |
| 2 | 1262646 | 660 | 608 | 0 | 126355 | 70.481689 | 0.944828 | -1.0 | -1.0 | 400.089236 | 87 |
| 3 | 1527863 | 783 | 683 | 0 | 126361 | 83.543192 | 0.864009 | -1.0 | -1.0 | 400.108237 | 50 |
| 4 | 1656733 | 839 | 628 | 0 | 126409 | 89.517499 | 0.923276 | -1.0 | -1.0 | 400.260259 | 116 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 123 | 45061971 | 3697 | 624 | 0 | 126396 | 392.637495 | 0.927586 | -1.0 | -1.0 | 400.219083 | 50 |
| 124 | 45687885 | 3719 | 634 | 0 | 126409 | 394.969046 | 0.916810 | -1.0 | -1.0 | 400.260259 | 50 |
| 125 | 46587721 | 3752 | 626 | 0 | 126401 | 398.465090 | 0.925431 | -1.0 | -1.0 | 400.234920 | 116 |
| 126 | 46594055 | 3752 | 636 | 0 | 126392 | 398.465090 | 0.914655 | -1.0 | -1.0 | 400.206414 | 87 |
| 127 | 46893656 | 3763 | 617 | 0 | 126401 | 399.630908 | 0.935129 | -1.0 | -1.0 | 400.234920 | 50 |
128 rows × 11 columns
Alternatively, a (partial) dictionary can be passed that describes the desired coordinates:
df = data[
{
"frame_indices": [1, 191],
"scan_indices": slice(300, 800, 10),
"mz_values": slice(None, 400.5),
"intensity_values": 50,
}
]
df
| raw_indices | frame_indices | scan_indices | precursor_indices | tof_indices | rt_values | mobility_values | quad_low_mz_values | quad_high_mz_values | mz_values | intensity_values | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 11009 | 1 | 690 | 0 | 98237 | 0.564402 | 0.856466 | -1.0 | -1.0 | 316.000994 | 50 |
| 1 | 14688 | 1 | 770 | 0 | 94768 | 0.564402 | 0.770259 | -1.0 | -1.0 | 306.313410 | 50 |
| 2 | 303435 | 191 | 740 | 0 | 109139 | 20.743806 | 0.802586 | -1.0 | -1.0 | 347.427845 | 50 |
Instead of returning a pd.DataFrame, it is also possible to return the raw indices of the ions that satisfy the filter by setting the last element of the slice to "raw":
indices = data[:400.5, 500:700, 0, 400.0: 400.5, [50, 87, 116], "raw"]
indices
array([ 221445, 1104358, 1262646, 1527863, 1656733, 1731685,
1834580, 1881013, 2123968, 2258316, 2560093, 2597723,
4610534, 4847408, 7994516, 8162820, 8437336, 9168710,
9178491, 9647218, 13696960, 14530934, 14902933, 16418582,
16422512, 16631196, 18217831, 18479187, 18726665, 18961259,
19448416, 19454152, 19454153, 19455509, 19456166, 19939773,
19957998, 20188944, 20191530, 20408960, 20419036, 20439657,
20668731, 20888042, 20894013, 20895950, 21158002, 21382721,
21388058, 21624059, 21863018, 23629117, 23865688, 24144170,
24145466, 25199967, 25201267, 25207043, 25736293, 25744631,
25996613, 26003284, 26017674, 26017675, 26803109, 27625200,
27919344, 27933607, 28451309, 28451902, 28474678, 29263587,
29545163, 30042520, 30308123, 30314972, 31129679, 31707287,
31718294, 31726560, 31997128, 32019944, 32566870, 33118131,
33391145, 33412635, 33968835, 34275408, 34580883, 34855018,
35695459, 36278859, 36835753, 37140980, 37433442, 37758349,
37762859, 38050210, 38053684, 38328211, 38618093, 38634438,
38909695, 38923640, 39220630, 39223097, 39784161, 40087198,
40659885, 40669594, 40670949, 40931863, 40959762, 41540560,
41822612, 41825654, 41837864, 42156040, 42996090, 43302248,
43596988, 43864191, 43882481, 45061971, 45687885, 46587721,
46594055, 46893656])
Converting these raw indices to the appropriate coordinates or even a whole pd.DataFrame can be done with convenience functions such as:
coordinate_dict = data.convert_from_indices(
indices,
return_rt_values=True,
return_tof_indices=True
)
coordinate_dict
{'tof_indices': array([126345, 126352, 126355, 126361, 126409, 126415, 126328, 126343,
126391, 126337, 126335, 126427, 126391, 126338, 126387, 126387,
126398, 126401, 126392, 126402, 126397, 126361, 126397, 126408,
126397, 126397, 126396, 126409, 126407, 126395, 126404, 126397,
126405, 126397, 126364, 126404, 126409, 126406, 126395, 126405,
126406, 126382, 126408, 126391, 126392, 126397, 126377, 126399,
126407, 126391, 126403, 126387, 126380, 126385, 126381, 126396,
126396, 126388, 126398, 126409, 126396, 126396, 126375, 126386,
126386, 126407, 126405, 126411, 126396, 126399, 126390, 126379,
126338, 126397, 126407, 126398, 126403, 126411, 126389, 126393,
126405, 126409, 126393, 126385, 126406, 126369, 126405, 126390,
126398, 126398, 126405, 126406, 126389, 126397, 126406, 126387,
126387, 126404, 126397, 126406, 126405, 126388, 126405, 126405,
126374, 126407, 126403, 126405, 126385, 126443, 126384, 126405,
126399, 126385, 126404, 126405, 126392, 126401, 126393, 126386,
126405, 126418, 126393, 126396, 126409, 126401, 126392, 126401],
dtype=uint32),
'rt_values': array([ 15.952364, 62.53361 , 70.481689, 83.543192, 89.517499,
93.439612, 98.741651, 100.032919, 112.54035 , 117.414695,
127.564265, 128.539861, 181.616486, 185.116779, 215.42888 ,
216.594252, 218.928011, 224.75686 , 224.75686 , 228.255341,
253.905582, 258.568707, 260.903007, 269.061553, 269.061553,
270.228397, 278.388836, 279.556035, 280.722093, 281.88576 ,
284.216758, 284.216758, 284.216758, 284.216758, 284.216758,
286.546947, 286.546947, 287.713942, 287.713942, 288.879763,
288.879763, 288.879763, 290.04581 , 291.21097 , 291.21097 ,
291.21097 , 292.376449, 293.541619, 293.541619, 294.707783,
295.873268, 304.034589, 305.201813, 306.365968, 306.365968,
311.03095 , 311.03095 , 311.03095 , 313.364331, 313.364331,
314.528855, 314.528855, 314.528855, 314.528855, 318.026799,
321.525534, 322.68959 , 322.68959 , 325.022786, 325.022786,
325.022786, 328.520427, 329.685302, 332.018241, 333.182612,
333.182612, 336.681116, 339.014098, 339.014098, 339.014098,
340.179476, 340.179476, 342.510083, 344.842494, 346.008036,
346.008036, 348.339887, 349.506183, 350.669559, 351.835915,
355.333532, 357.664273, 359.996934, 361.163244, 362.329056,
363.496709, 363.496709, 364.661721, 364.661721, 365.826367,
366.992833, 366.992833, 368.155896, 368.155896, 369.321814,
369.321814, 371.653634, 372.820294, 375.149367, 375.149367,
375.149367, 376.316335, 376.316335, 378.647557, 379.814536,
379.814536, 379.814536, 380.979401, 384.477247, 385.642353,
386.807969, 387.974738, 387.974738, 392.637495, 394.969046,
398.46509 , 398.46509 , 399.630908])}
df = data.as_dataframe(indices)
df
| raw_indices | frame_indices | scan_indices | precursor_indices | tof_indices | rt_values | mobility_values | quad_low_mz_values | quad_high_mz_values | mz_values | intensity_values | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 221445 | 146 | 575 | 0 | 126345 | 15.952364 | 0.980388 | -1.0 | -1.0 | 400.057569 | 87 |
| 1 | 1104358 | 585 | 682 | 0 | 126352 | 62.533610 | 0.865086 | -1.0 | -1.0 | 400.079736 | 50 |
| 2 | 1262646 | 660 | 608 | 0 | 126355 | 70.481689 | 0.944828 | -1.0 | -1.0 | 400.089236 | 87 |
| 3 | 1527863 | 783 | 683 | 0 | 126361 | 83.543192 | 0.864009 | -1.0 | -1.0 | 400.108237 | 50 |
| 4 | 1656733 | 839 | 628 | 0 | 126409 | 89.517499 | 0.923276 | -1.0 | -1.0 | 400.260259 | 116 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 123 | 45061971 | 3697 | 624 | 0 | 126396 | 392.637495 | 0.927586 | -1.0 | -1.0 | 400.219083 | 50 |
| 124 | 45687885 | 3719 | 634 | 0 | 126409 | 394.969046 | 0.916810 | -1.0 | -1.0 | 400.260259 | 50 |
| 125 | 46587721 | 3752 | 626 | 0 | 126401 | 398.465090 | 0.925431 | -1.0 | -1.0 | 400.234920 | 116 |
| 126 | 46594055 | 3752 | 636 | 0 | 126392 | 398.465090 | 0.914655 | -1.0 | -1.0 | 400.206414 | 87 |
| 127 | 46893656 | 3763 | 617 | 0 | 126401 | 399.630908 | 0.935129 | -1.0 | -1.0 | 400.234920 | 50 |
128 rows × 11 columns
AlphaTims' plotting module provides a few convenient plots. Note that they can only be used if the gui option is used during installation (pip install "alphatims[plotting]"). In this tutorial we will also load the holoviews package to save our (interactive) plots.
import holoviews as hv
A key plot that is always useful before diving in the data is a total ion chromatogram (TIC):
tic = alphatims.plotting.tic_plot(data, title=data.sample_name, width=900)
hv.save(tic, "tutorial_tic.html")
tic
Other useful plots include heatmaps in different dimensions. For instance, we can check the calibrant spray that is used for the TIMS:
calibrant_mz = 1221.990637
ppm_error = 5
calibrant_low_mz = calibrant_mz / (1 + ppm_error / 10**6)
calibrant_high_mz = calibrant_mz * (1 + ppm_error / 10**6)
df = data[:, :, :, calibrant_low_mz: calibrant_high_mz]
heatmap = alphatims.plotting.heatmap(
df,
x_axis_label="rt",
y_axis_label="mobility",
title=data.sample_name,
width=900
)
hv.save(heatmap, "tutorial_heatmap.html")
heatmap
Of course we can also investigate 1D plots such as spectra for individual precursors of interest (not that this requires "raw" indices as input and not a pd.DataFrame):
precursor_indices = data[:, :, 9999, "raw"]
spectrum = alphatims.plotting.line_plot(
data,
precursor_indices,
x_axis_label="mz",
width=900
)
hv.save(spectrum, "tutorial_spectrum.html")
spectrum
AlphaTims was developed to access both ddaPASEF and diaPASEF. Importing a DIA sample (available for download on AlphaTims' GitHub page) is done in exactly the same way as importing a DDA sample:
bruker_dia_d_folder_name = "/Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_high_speed_21min_8cm_S1-C8_1_22474.d"
dia_data = alphatims.bruker.TimsTOF(bruker_dia_d_folder_name)
2021-04-22 16:59:24> Importing data from /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_high_speed_21min_8cm_S1-C8_1_22474.d 2021-04-22 16:59:24> Reading frame metadata for /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_high_speed_21min_8cm_S1-C8_1_22474.d 2021-04-22 16:59:24> Reading 11,868 frames with 730,564,765 detector strikes for /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_high_speed_21min_8cm_S1-C8_1_22474.d
100%|██████████| 11868/11868 [00:13<00:00, 911.13it/s]
2021-04-22 16:59:37> Indexing /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_high_speed_21min_8cm_S1-C8_1_22474.d...
2021-04-22 16:59:38> Succesfully imported data from /Users/swillems/Data/alphatims_testing/20201207_tims03_Evo03_PS_SA_HeLa_200ng_EvoSep_prot_high_speed_21min_8cm_S1-C8_1_22474.d
With AlphaTims slicing mechanism, it is possible to e.g. manually extract fragment traces from a precursor and overlay them in a single XIC. An example is the following peptide:
and fragments:
| Seq | # | B | Y | # |
|---|---|---|---|---|
| Y | 1 | 164.07065 | 973.44145 | 7 |
| N | 2 | 278.11358 | 810.37812 | 6 |
| D | 3 | 393.14052 | 696.33520 | 5 |
| T | 4 | 494.18820 | 581.30825 | 4 |
| F | 5 | 641.25661 | 480.26057 | 3 |
| W | 6 | 827.33592 | 333.19216 | 2 |
| K | 7 | 955.43089 | 147.11285 | 1 |
ppm = 50
rt_tolerance = 30
mobility_tolerance = 0.05
precursor_mz = 487.22439
precursor_mobility = 0.81
precursor_rt = 10.011 * 60
fragment_mzs = {
"b1": 164.07065,
"b2": 278.11358,
"b3": 393.14052,
"b4": 494.18820,
"b5": 641.25661,
"b6": 827.33592,
"b7": 955.43089,
"y7": 973.44145,
"y6": 810.37812,
"y5": 696.33520,
"y4": 581.30825,
"y3": 480.26057,
"y2": 333.19216,
"y1": 147.11285,
}
rt_slice = slice(precursor_rt - rt_tolerance, precursor_rt + rt_tolerance)
im_slice = slice(
precursor_mobility - mobility_tolerance,
precursor_mobility + mobility_tolerance
)
precursor_mz_slice = slice(
precursor_mz / (1 + ppm / 10**6),
precursor_mz * (1 + ppm / 10**6)
)
precursor_xic = alphatims.plotting.line_plot(
dia_data,
dia_data[rt_slice, im_slice, 0, precursor_mz_slice, "raw"],
x_axis_label="rt",
width=900,
remove_zeros=True,
label="precursor"
)
xic_overlay = precursor_xic
for fragment_name, mz in fragment_mzs.items():
fragment_xic = alphatims.plotting.line_plot(
dia_data,
dia_data[
rt_slice,
im_slice,
precursor_mz_slice,
mz / (1 + ppm / 10**6): mz * (1 + ppm / 10**6),
"raw"
],
x_axis_label="rt",
width=900,
remove_zeros=True,
label=fragment_name,
)
xic_overlay *= fragment_xic.opts(muted=True)
xic_overlay.opts(hv.opts.Overlay(legend_position='bottom'))
xic_overlay.opts(hv.opts.Overlay(click_policy='mute'))
xic_overlay = xic_overlay.opts(show_legend=True)
hv.save(xic_overlay, "tutorial_dia_xic_overlay.html")
xic_overlay